<?php
class am4Menu extends am4Plugin{
    private $slug = 'am4-settings';
    function action_AdminMenu(){
        add_menu_page('aMember', 'aMember', 'administrator', $this->slug);
        foreach(get_declared_classes() as $c){
            if(preg_match('/am4MenuPage_(\S+)/',$c,$regs)){
                $this->addMenuItem("am4-".strtolower($regs[1]), $c);
            }
        }
        
    }
    
    
    function addMenuItem($slug,  $class){
        $title = call_user_func(array($class, 'getTitle')); 
        $a = add_submenu_page($this->slug, $title, $title,'administrator', $slug, am4PluginsManager::createController($class));
        if(method_exists($class, 'staticAction')){
    	    add_action('load-'.$a, array($class, 'staticAction'));
        }
    }
}



class am4MenuPageController extends am4FormController{
    
    static function getTitle(){
        throw new Exception("getTitle should be overriden in childs");
    }
    
    
    function preDispatch(){
        
    }
    
}



class am4MenuPageFormController extends am4MenuPageController{
    function preDispatch() {
        parent::preDispatch();
        if(!current_user_can('manage_options'))
            return '';

        // Verify nonce
        if(am4Request::$method=='POST' && !check_admin_referer(get_class())){
            throw new Exception('Security check!');
        }
        $this->amPostScript();
        ?>
        <div class="wrap">
            <div id="icon-options-general" class="icon32"><br /></div>
            <h2><?php  _e($this->getTitle());?></h2>
            <form id="amember-settings-form" method="POST" action="">
            <?php 
            wp_nonce_field(get_class());
        
    return true;
            
    }
    function postDispatch() {
        parent::postDispatch();
        $this->actionInput("save");
        ?>
            <input type="submit" class="button-primary" name="save" value="Apply Changes">
            </form>
        </div>

        <?php
        
    }
}



class am4MenuPage_settings extends am4MenuPageFormController{
    static function getTitle(){
        return __("Settings", 'am4-plugin');
    }
    function getOptions(){
        $options = am4Settings::getInstance()->getAll();
        if(empty($options['user_action']) || empty($options['guest_action'])) $options = array_merge($options, $this->getProtectionDefaults());
        if(empty($options['disable_protection'])) $options['disable_protection'] = array('administrator');
        return $options;
    }
    
    
    function saveForm($options){
        am4Settings::getInstance()->setAll($options);
    }
    
    function validate($options){
        try{
            am4PluginsManager::initAPI($options['path']);
        }catch(Exception $ex){
            return $ex->getMessage();
        }
        return true; 
    }
    static function staticAction(){
        if(am4Request::$method!='POST') return;
        if(!current_user_can('manage_options'))
	    return '';
	if(!check_admin_referer('am4MenuPageFormController')){
	    throw new Exception('Security check!');
	}
	$options = get_magic_quotes_gpc() ? stripslashes_deep(am4Request::get('options')) : am4Request::get('options');

    	try{
	  am4PluginsManager::initAPI($options['path']);
	}catch(Exception $e){
	  
	}
    }
    
    function doAjaxValidate(){
        if(($err = $this->validate(array('path' => am4Request::get('path')))) === true){
            $am = Am_Lite::getInstance();
            $e = new aMemberJson();
            $e->valid=1;
            $e->url = $am->getRootURL();
            echo $e;
        }else{
            $e = new aMemberJsonError($err);
            echo $e;
        }
        
    }
    
    function doAjaxBrowse(){
        $dirOrig = am4Request::get('dir', ABSPATH);
        $dirOrig = is_dir($dirOrig) ? $dirOrig : ABSPATH;

        $selected = am4Request::get('selected', false);

        $dir = ($selected) ? dirname($dirOrig) : $dirOrig;
        $dir = realpath($dir);

        if (!is_dir($dir)) {
            $dir = ABSPATH;
        }


        $dirList = $this->getDirList($dir);

        if ($selected) {
            foreach ($dirList as $k => $dirDescription) {
                if ($dirDescription['path'] == $dirOrig) {
                    $dirList[$k]['selected'] = true;
                    break;
                }
            }
        }

        $currentDir = $this->getCurrentDir($dir);
        $prevDir = $this->getPrevDir($dir);

        $result = array(
            'dirList' => $dirList,
            'currentDir' => $currentDir,
            'prevDir' => $prevDir,
            'separator' => DIRECTORY_SEPARATOR
        );

        aMemberJson::init($result)->send();
    }
        
    protected function getCurrentDir($dir)
    {
        $result = array();
        $dirParts = explode(DIRECTORY_SEPARATOR, $dir);

        $path = array();
        foreach ($dirParts as $part) {
            $path[]= $part;

            $part_path = implode(DIRECTORY_SEPARATOR, $path);
            $dir = array (
                'name' => $part,
                'path' => ($this->checkChRoot($part_path) ? $part_path : null )
            );
           $result[] = $dir;
        }
        
        return $result;
    }

    protected function getPrevDir($dir)
    {
        $prevDir = null;

        $prevDirPath = dirname($dir);

        //root of file system
        if ($prevDirPath == $dir) return null;

        $dirParts = explode(DIRECTORY_SEPARATOR, $prevDirPath);

        $prevDirName = end($dirParts);

        if (is_dir( $prevDirPath ) ) {
            $prevDir = array (
                'name' => $prevDirName,
                'path' => ($this->checkChRoot($prevDirPath) ? $prevDirPath : null)
            );
        }

        return $prevDir;
    }

    protected function getDirList($dir)
    {
        $result = array();
        $dirName = $dir;
        
        $dirHandler = opendir($dirName);
        while($fn = readdir($dirHandler)) {
            if (is_dir($dirName . DIRECTORY_SEPARATOR . $fn) &&
                    !in_array($fn, array('..', '.'))) {
                
                $result[] = $this->getDirRecord($dirName, $fn);
            }
        }
        closedir($dirHandler);

        usort($result, create_function('$a,$b', '
            if ($a["name"]>$b["name"]) {
                return 1;
            } elseif ($a["name"]==$b["name"]) {
                return 0;
            } else {
                return -1;
            }
        '));
        
        return $result;
    }

    protected function getDirRecord($dirName, $fn)
    {
        $stat = stat($dirName . DIRECTORY_SEPARATOR . $fn);

        $dir = array(
            'name' => $fn,
            'path' => $dirName . DIRECTORY_SEPARATOR . $fn,
            'url' => $this->guessUrl($dirName . DIRECTORY_SEPARATOR . $fn),
            'perm' => $this->formatPermissions($stat['mode']),
            'created' => $this->formatDate($stat['ctime']),
            'selected' => false
        );
        return $dir;
    }

    public function guessUrl($dir)
    {
        $documentRootFixed = str_replace('/', DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT']);
        //check if it is possible to calculate url
        if (strpos($dir, $documentRootFixed) !== 0) return false;

        $rootUrlMeta = parse_url(get_option('blog_url'));

        //combine url
        return sprintf('%s://%s%s/%s',
            $rootUrlMeta['scheme'],
            $rootUrlMeta['host'],
            (isset($rootUrlMeta['port']) ? ':' . $rootUrlMeta['port'] : ''),
            trim(str_replace(DIRECTORY_SEPARATOR, '/', str_replace($documentRootFixed, '', $dir)), '/')
        );

    }

    protected function formatPermissions($p){
        $res = '';
        $res .= ($p & 256) ? 'r' : '-';
        $res .= ($p & 128) ? 'w' : '-';
        $res .= ($p & 64) ?  'x' : '-';
        $res .= ' ';
        $res .= ($p & 32) ?  'r' : '-';
        $res .= ($p & 16) ?  'w' : '-';
        $res .= ($p & 8) ?   'x' : '-';
        $res .= ' ';
        $res .= ($p & 4) ?   'r' : '-';
        $res .= ($p & 2) ?   'w' : '-';
        $res .= ($p & 1) ?   'x' : '-';
        return $res;
    }

    protected function formatDate($tm){
        return strftime("%m/%d/%Y %H:%M:%S", $tm);
    }

    protected function checkChRoot($dir) 
    {
        if (!is_null($this->chroot) &&
            strpos($dir, $this->chroot)!==0) {
            return false;
        } else {
            return true;
        }
    }


    
}

class am4MenuPage_styles extends am4MenuPageFormController{
    protected $styles = array('widget_login_form.phtml', 'widget_after_login.phtml');
    static function getTitle(){
        return __('Templates', 'am4-plugin');
    }
    function saveForm($options){
        foreach($options as $k=>$v){
            if(!in_array($k,$this->styles)) unset($options[$k]);
        }
        foreach($this->styles as $f){
            $file = file_get_contents(AM4_PLUGIN_DIR."/views/".$f);
            if(strcmp(trim($file), trim($options[$f]))=== 0) unset($options[$f]);
        }
        if($options) update_option(AM4_STYLE_OPTION, $options);
    }
    
    function getOptions(){
        $options = get_option(AM4_STYLE_OPTION);
        foreach($this->styles as $s){
            if(!$options[$s]){
                $options[$s] = file_get_contents(AM4_PLUGIN_DIR."/views/".$s);
            }
        }
        return ($options ? $options : array());
        
    }
    
}


class am4MenuPage_errormessages extends am4MenuPageFormController{
    protected $simple;
    
    function __construct($simple = false){
        $this->simple = $simple;
    }
    static function getTitle(){
        return __('Error Messages', 'am4-plugin');
    }
    
    function isSimple(){
        return  $simple;
    }
    function postDispatch(){
        return; // doNothing;
    }
    function saveForm($options){
        $errors = $this->getOptions();
        if($options['id']){
            $errors[$options['id']] = $options;
        }else{
            $errors[] = $options;
        }
        update_option(AM4_ERROR_OPTION, $errors);
    }
    
    function getOptions(){
        $options = get_option(AM4_ERROR_OPTION);
        return ($options ? $options : array());
    }
    function doAjaxDelete(){
        $id = am4Request::getInt('id');
        $options = $this->getOptions();
        unset($options[$id]);
        update_option(AM4_ERROR_OPTION, $options);
    }
}
